﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;

namespace _14_缓存.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class 内存缓存Controller : ControllerBase
    {
        private readonly IMemoryCache memoryCache;
        private readonly ILogger<内存缓存Controller> logger;
        public 内存缓存Controller(IMemoryCache memoryCache, ILogger<内存缓存Controller> logger)
        {
            this.memoryCache = memoryCache;
            this.logger = logger;
        }
        // 推荐使用，推荐使用，推荐使用，推荐使用
        [HttpGet]
        public async Task<ActionResult<Book?>> GetBook(int id)
        {
            //logger.LogInformation($"开始执行GetBook,id={id}");
            Console.WriteLine($"开始执行GetBook,id={id}");
            Book? b = await memoryCache.GetOrCreateAsync<Book?>("Book" + id,
                async (e) =>
                {
                    // logger.LogInformation($"缓存中没有查到，到数据库中查一查，id={id}");
                    Console.WriteLine($"缓存中没有查到，到数据库中查一查，id={id}");
                    // 绝对过期策略
                    // e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60);  //设置缓存时间，默认是无期限
                    e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Random.Shared.Next(50, 60)); //生成个随机值（50-60之间） 作为缓存时间  可以防止缓存雪崩
                    // 滑动过期时间 只要没有过期，访问到就会把有效期延长
                    e.SlidingExpiration = TimeSpan.FromSeconds(10);

                    // 绝对过期和滑动过期 可以一起用，绝对过期时间大于滑动时间，只要绝对过期时间没到，就会一直被续命

                    return await MyDbContext.GetByIdAsync(id);
                }
            );
            // logger.LogInformation($"查询结果{b}");
            Console.WriteLine($"查询结果{b}");
            if (b == null)
            {
                return NotFound($"没有ID={id}的书");
            }
            else
            {

                return b;
            }

        }
    }
  
    public record Book(int id,string name);

    public class MyDbContext
    {
        public static Book? GetById(int id)
        {
            switch (id)
            {
                case 0:
                    return new Book(0, "000000");
                case 1:
                    return new Book(1, "111111111111");
                case 2:
                    return new Book(2, "222222222");
                default:
                    return null;
            }
        }
        public static Task<Book?> GetByIdAsync(int id)
        {
            var result = GetById(id);
            return Task.FromResult(result);
        }
    }
}
